package nexus.com.list
{
	import com.ux.event.DragBarEvent;
	
	import flash.events.MouseEvent;
	
	import nexus.com.container.ScrollContainer;
	import nexus.event.ListEvent;

	
	[Event(name="listSelectionChange", type="nexus.event.ListEvent")]
	
	
	
	public class List extends ScrollContainer
	{
		
		//-----------------------------------------------------------------------------------
		//
		// private
		//
		//-----------------------------------------------------------------------------------
		private var _dataProvider : Array;
		private var _labelField : String = "label";
		private var _list : Array = [];
		private var _gcList : Array = [];
		private var _selectedIndex : int = -1;
		private var _selectedData : Object = null;
		
		//-----------------------------------------------------------------------------------
		//
		// protected vars
		//
		//-----------------------------------------------------------------------------------
		
		
		//-----------------------------------------------------------------------------------
		//
		// public vars
		//
		//-----------------------------------------------------------------------------------
		
		
		
		//-----------------------------------------------------------------------------------
		//
		// constructor
		//
		//-----------------------------------------------------------------------------------
		public function List()
		{
			super();
		}
		
		
		//-----------------------------------------------------------------------------------
		//
		// setter / getter
		//
		//-----------------------------------------------------------------------------------

		public function get selectedLabel():String
		{
			return _dataProvider[selectedIndex][labelField];
		}

		public function get selectedData():Object
		{
			return _selectedData;
		}

		public function set selectedData(value:Object):void
		{
			_selectedData = value;
			listItemSelectControl();
		}

		public function get selectedIndex():int
		{
			return _selectedIndex;
		}

		public function set selectedIndex(value:int):void
		{
			_selectedIndex = value;
			selectedData = ( _selectedIndex > -1 && 
				_selectedIndex < dataProvider.length ) ? dataProvider[ _selectedIndex ] : null;
		}

		public function get labelField():String
		{
			return _labelField;
		}

		public function set labelField(value:String):void
		{
			_labelField = value;
			
			var len:int = _list.length;
			for (var i:int = 0; i < len; i++) 
			{
				_list[i].label = _dataProvider[ i ][_labelField];
			}
		}

		public function set dataProvider( data : Array ):void
		{
			
			_dataProvider = data;
			selectedIndex = -1;
			// defaultItemHeight가 설정되어있지 않으면 최초 아이템 1개 생성하여 셋팅하여 봄.
			if( defaultItemHeight == 0 )
			{
				var item : ListItem = getItem() as ListItem;
				itemDefaultSetting( item, _dataProvider[ 0 ] );
				defaultItemHeight = item.viewHeight;
			}
			updateItemList();
			resetScroll();
		}
		
		public function get dataProvider():Array
		{
			return _dataProvider;
		}
		
		
		
		
		
	
		
		
		//-----------------------------------------------------------------------------------
		//
		// public function
		//
		//-----------------------------------------------------------------------------------
		
		
		override public function updateDisplayList():void
		{
			super.updateDisplayList();
			
			if( _dataProvider != null )
			{
				updateItemList();
			}
			
		}
		
		
		//-----------------------------------------------------------------------------------
		//
		// protected function
		//
		//-----------------------------------------------------------------------------------
		protected var defaultItemHeight : Number = 0; // 아이탬 0 번의 기본 viewHeight
		protected var extraItemNum : int = 6; // 화면을 벗어난 여유분 아이템 갯수 - 짝수 권장.
		
		
		/**
		 * 화면 사이즈 + extraItemNum 만큼의 리스트 유지를 위한 메서드
		 */		
		protected function updateItemList():void
		{
			var item : ListItem;

			// 리스트에서 전부 가비지로 이동.
			this.removeAllElement();
			if( _list.length > 0 )
			{
				for each( item in _list )
				{
					_gcList.push( item );
				}
				
				_list.length = 0;
			}
			
			var dataStartNum : int = Math.ceil( (-wrapperContainer.y)/defaultItemHeight )- Math.ceil( extraItemNum/2 );
			
			var maxHeight : Number = this.maskClip.height + ( defaultItemHeight*extraItemNum );
			var len:int = Math.min( _dataProvider.length, Math.ceil( maxHeight/defaultItemHeight ) );
			dataStartNum = Math.max( Math.min( dataStartNum , dataProvider.length-len ), 0 );
			for (var i:int = 0; i < len; i++) 
			{
				item = getItem() as ListItem;
				if( i+dataStartNum < _dataProvider.length ) 
					itemDefaultSetting( item, _dataProvider[ i+dataStartNum ] );
				item.y = defaultItemHeight*(dataStartNum+i);
				addElement( item );
				_list.push( item );
			}
			
			this.wrapContainerHeight = dataProvider.length * defaultItemHeight;
			listItemSelectControl();
		}
		
		
		/**
		 * @return list 재활용 메서드 
		 */		
		protected function getItem():*
		{
			if( _gcList.length > 0 )
			{
				return _gcList.pop();
			}
			
			var item : ListItem = new ListItem();
			return item;
		}
		
		/**
		 * 리스트 아이템 기본 셋팅.
		 * @param __item 리스트 아이템
		 * @param dp
		 */		
		protected function itemDefaultSetting( __item : ListItem, dp : Object ):void
		{
			__item.data = dp;
			__item.label = dp[_labelField];
			__item.viewWidth = ( isNeedVscroll ) ? viewWidth-verticalScroll.width-paddingLeft-paddingRight : viewWidth-paddingLeft-paddingRight;
			__item.x = paddingLeft;
			
				
				
			__item.buttonMode = true;
			__item.addEventListener(MouseEvent.ROLL_OVER, onItemOver );
			__item.addEventListener(MouseEvent.ROLL_OUT, onItemOut );
			__item.addEventListener(MouseEvent.CLICK, onItemClick );
		}
		//-----------------------------------------------------------------------------------
		//
		// private function
		//
		//-----------------------------------------------------------------------------------
		
		private function getIndexByData( data:Object ):int
		{
			var len:int = _dataProvider.length;
			for (var i:int = 0; i < len; i++) 
			{
				if( _dataProvider[ i ] == data ) return i;
			}
			
			return -1;
		}
		
		
		private function listItemSelectControl():void
		{
			var len:int = _list.length;
			for (var i:int = 0; i < len; i++) 
			{
				if( _list[ i ].data == _selectedData ) _list[ i ].ON();
				else _list[ i ].OFF();
			}
		}
		
		//-----------------------------------------------------------------------------------
		//
		// event handler
		//
		//-----------------------------------------------------------------------------------
		
		override protected function onVScrollEvent(e:DragBarEvent):void
		{
			super.onVScrollEvent( e );
			updateItemList();
		}
		
		
		protected function onItemClick(e:MouseEvent):void
		{
			var idx : int = getIndexByData( e.currentTarget.data );
			_selectedIndex = idx;
			_selectedData = e.currentTarget.data;
			
			listItemSelectControl();
			
			var le : ListEvent = new ListEvent( ListEvent.LIST_SELECTION_CHANGE );
			le.data = e.currentTarget.data;
			dispatchEvent( le );
		}
		
		protected function onItemOut(e:MouseEvent):void
		{
			if( e.currentTarget.data != _selectedData )
			{
				e.currentTarget.OFF();
			}
		}
		
		protected function onItemOver(e:MouseEvent):void
		{
			e.currentTarget.ON();
		}
		
		
		//-----------------------------------------------------------------------------------
		//
		// destory
		//
		//-----------------------------------------------------------------------------------
		override public function destory():void
		{
			super.destory();
		}
		
		
		
		
		
		
		
		
	}
}